using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework;

namespace GameStateManagement.View.Sprites
{
    public class SpriteManager
    {
        #region Fields

        private static ContentManager _content;
        private static Dictionary<String, Texture2D> _sprites;
        private static Dictionary<String, SpriteFont> _spriteFonts;
        private static Dictionary<String, Color[]> _collisionMaps;

        #endregion

        #region Properties

        public static Game Game { get; set; }

        #endregion

        public SpriteManager(Game game)
        {
            _content = new ContentManager(game.Services, "Content");
            _sprites = new Dictionary<string, Texture2D>();
            _spriteFonts = new Dictionary<string, SpriteFont>();
            _collisionMaps = new Dictionary<String, Color[]>();
        }

        /// <summary>
        /// Loads a texture into the manager.
        /// </summary>
        /// <param name="fileName">Name of imagefile to load.</param>
        /// <returns>The loaded texture</returns>
        public Texture2D LoadSprite(String fileName)
        {
            if (_sprites.ContainsKey(fileName))
                return GetSprite(fileName);

            Texture2D texture = null;
            try
            {
                texture = _content.Load<Texture2D>(fileName);
                _sprites.Add(fileName, texture);
                _collisionMaps.Add(fileName, CreateCollisionData(texture));
            }
            catch (Exception)
            { }
     
            return texture;
        }

        /// <summary>
        /// Creates collision data to use with per-pixel collision detection.
        /// </summary>
        /// <param name="texture">Texture to create data for.</param>
        /// <returns>The collision data.</returns>
        private static Color[] CreateCollisionData(Texture2D texture)
        {
            var collisionData = new Color[texture.Width * texture.Height];

            // Extract collision data
            texture.GetData(collisionData);

            return collisionData;
        }


        /// <summary>
        /// Gets collision data for a .
        /// </summary>
        /// <param name="textureName">Name of texture</param>
        /// <returns>The loaded sprite</returns>
        public Color[] GetCollisionData(String textureName)
        {
            Color[] data;

            _collisionMaps.TryGetValue(textureName, out data);

            return data;
        }

        /// <summary>
        /// Loads a sprite into the manager.
        /// </summary>
        /// <param name="fileName">Name of font to load.</param>
        /// <returns>The loaded font</returns>
        public SpriteFont LoadSpriteFont(String fileName)
        {
            var font = _content.Load<SpriteFont>(fileName);
            _spriteFonts.Add(fileName, font);
            return font;
        }

        /// <summary>
        /// Tries to get a texture, if not loaded tries to load it. returns null if not loaded or not found.
        /// </summary>
        /// <param name="textureName">Name of sprite</param>
        /// <returns>The loaded sprite</returns>
        public Texture2D GetSprite(String textureName)
        {
            Texture2D texture;
            if (!_sprites.TryGetValue(textureName, out texture))
            {
                try
                {
                    texture = LoadSprite(textureName);
                }
                catch (Exception)
                {
                    texture = null;
                }
            }

            return texture;
        }

        /// <summary>
        /// Tries to get a font, if not loaded tries to load it. returns null if not loaded or not found.
        /// </summary>
        /// <param name="name">Name of sprite</param>
        /// <returns>The loaded font</returns>
        public SpriteFont GetSpriteFont(String name)
        {
            SpriteFont font;
            if (!_spriteFonts.TryGetValue(name, out font))
            {
                try
                {
                    font = LoadSpriteFont(name);
                }
                catch (Exception)
                {
                    font = null;
                }
            }

            return font;
        }

        /// <summary>
        /// Clears all loaded textures and fonts.
        /// </summary>
        public void ClearSprites()
        {
            _sprites.Clear();
            _spriteFonts.Clear();
            _collisionMaps.Clear();
            _content.Unload();
        }
    }
}
